Nushellでuvを使いPythonの開発環境を構築する方法

Nushellでuvを使いPythonの開発環境を構築する方法

Clock Icon2024.10.31

しばたです。

私は普段必要になったときだけPythonの開発環境を整備するのですが、最近常用するシェルをNushellに変えたことで改めて開発環境について検討しなおす必要がありました。

本記事ではNushellでPythonの開発環境を構築する際に検討すべきポイントと、開発環境の整備にuvを使ってみたのでその結果を共有しようと思います。

はじめに

NushellでPythonの開発環境を構築する際に検討すべきポイント

一般的にPythonの開発環境を選定する基準として

  • Python自体のバージョン管理
  • 仮想環境の管理
  • パッケージ管理

の3つの軸があるかと思います。
これらの軸に関してNushellから見た観点を書いていきます。

Python自体のバージョン管理

Python自体のバージョン管理についてはpyenvpyenv-winを筆頭にいくつかのツールが対応しています。
私の知る限りではシステムグローバルに利用するPythonのバージョンを切り替えられるのはpyenvとpyenv-winだけの様で、他のツールでは仮想環境単位で利用するPythonのバージョンを切り替える形になっています。

このためグローバルにPythonのバージョンを切り替えるにはpyenvとpyenv-winを使う必要がありますが、Nushellとしては以下のドキュメントに利用法が記載されています。

Nushell
# Nushell での pyenv および pyenv-win の設定方法

# MacOS or Linux : pyenv
$env.PATH = ($env.PATH | split row (char esep) | prepend $"(pyenv root)/shims")

# Windows : pyenv-win
$env.Path = ($env.Path | split row (char esep) | prepend $"~/.pyenv/pyenv-win/bin/pyenv.ps1")

pyenvとpyenv-winだけあれば事足りる場合はNushellでもそのまま両者を採用できます。
(なお、pyenvやpyenv-win側でNushellの利用が公式サポートされているわけでは無いのでそこはご留意ください。)

その他ツールが必要な場合はNushellで仮想環境の管理がサポートされていれば利用可能という形になります。

仮想環境の管理

仮想環境の管理はvirtualenvを祖として様々なツールで同等の機能が実装されており、Python 3.3から標準機能としてvenvも使える様になっています。
virtualenv以外のツールについてvenvはvirtualenvのサブセットとなる独自実装であり、その他ツールでは「内部的にvirtualenvを呼び出す」か「virtualenvをベースにした独自実装」のパターンが多い様です。

Nushellの対応状況としては、virtualenvは2021年リリースのv20.8.0からNushellをサポートしています。

venvではPython本体のリリースサイクルとNushellの更新状況が合わない[1]ことからサポートが見送られています。

その他ツールに関しては、たとえば今回採用したuvではvirtualenvを元にした独自実装で仮想環境を管理している様で、Nushellもサポートしておりvirtualenvから流用したと思しきアクティベーションスクリプト(activate.nu)を使う形になっています。

ざっくりまとめておくと、

  • venvはNushellをサポートする見込みが低いので利用は諦めるしかない
  • venvの代わりにvirtualenvを使う
  • 独自ツールでもvirtualenvの派生であればNushellをサポートする可能性が高い

といった感じです。

パッケージ管理

パッケージ管理についてはシェル依存の部分が無いのでNushellでの利用において特筆すべき点はありません。

「ワイルドカード等の特殊文字の扱いがシェルによって異なるため、Nushellではコマンドの指定方法を変える必要がある」といったケースはあり得ますが、本記事の主題ではないのでこれ以上は触れません。

Why uv?

今回Pythonの開発環境を作るにあたりuvを選びました。

https://docs.astral.sh/uv/

もともと私はPythonのバージョン管理に関して「pyenvでPythonをソースからビルドするのがしんどい」という理由でRyeを使っていました。

ただ、Rye自体も「まずはプロジェクトありき」という印象で、シンプルにPythonのバージョン管理だけしたい、仮想環境だけ管理したい自分にとっては少しオーバースペックに感じていました。

その後uvを知り試してみたら自分にとって丁度良い機能と操作感だったのでそのまま利用しているのが現状になります。
Pythonに詳しく無いのでuv以外を知らない(でも特段困っていない)という消極的な理由もあります。

Nushellのサポート状況は後から調べたのですが普通にサポートしてたのでラッキーでした。

試してみた

ここからは実際にNushell上でuvのインストールと動作確認をしていきます。

検証環境

今回は私の開発PCを検証環境として使います。

  • Windows 11 Pro (23H2)
  • Nushell 0.99.1

Windows環境ですがインストール以外は他のOSでも同等の結果になるはずです。

uvのインストール

Windows環境での公式なインストール方法は専用のインストールスクリプトをダウンロードして実行する形になっています。

ただ、私が普段使うScoopでもインストール可能だったので今回はこちらを採用します。

Scoop本体はPowerShell製ですがscoopコマンド自体はcmdファイルなのでNushellでも使えます。

Nushell
# Nushell上でもscoopコマンドは普通につかえる
# scoop install uv コマンドで uvをインストール
scoop install uv

インストール結果はこんな感じで今回はVer.0.4.29がインストールされました。

Nushell
~> which uv
╭───┬─────────┬─────────────────────────────────────┬──────────╮
│ # │ command │                 path                │   type   │
├───┼─────────┼─────────────────────────────────────┼──────────┤
│ 0 │ uv      │ C:\Users\shibata\scoop\shims\uv.exe │ external │
╰───┴─────────┴─────────────────────────────────────┴──────────╯
~> uv --version
uv 0.4.29 (85f9a0d0e 2024-10-30)

Pythonのバージョン管理

uvで使うPythonのバージョン管理はuv pythonコマンドで行います。
例えばPython 3.11をインストールする場合は以下の様にuv python installコマンドを実行します。

Nushell
uv python install 3.11

結果を確認するとこんな感じです。
Windowsに事前にインストール済みだったPython 3.12と一緒に3.11も追加されたのが見て取れます。

Nushell
# Python 3.11 をインストール
~> uv python install 3.11
Installed Python 3.11.10 in 16.75s
 + cpython-3.11.10-windows-x86_64-none

# インストール済みのPythonをチェック
~> uv python list
cpython-3.13.0+freethreaded-windows-x86_64-none    <download available>
cpython-3.12.7-windows-x86_64-none                 AppData\Local\Microsoft\WindowsApps\PythonSoftwareFoundation.Python.3.12_qbz5n2kfra8p0\python.exe
cpython-3.12.7-windows-x86_64-none                 <download available>
cpython-3.11.10-windows-x86_64-none                AppData\Roaming\uv\python\cpython-3.11.10-windows-x86_64-none\python.exe
cpython-3.10.15-windows-x86_64-none                <download available>
cpython-3.9.20-windows-x86_64-none                 <download available>
cpython-3.8.20-windows-x86_64-none                 <download available>
cpython-3.7.9-windows-x86_64-none                  <download available>
pypy-3.10.14-windows-x86_64-none                   <download available>
pypy-3.9.19-windows-x86_64-none                    <download available>
pypy-3.8.16-windows-x86_64-none                    <download available>
pypy-3.7.13-windows-x86_64-none                    <download available>

現在uvではシステムグローバルにPythonのバージョンを切り替えることはできないので、別途仮想環境を作ってやる必要があります。

仮想環境の作成とアクティベーション

uvで仮想環境を作るにはuv venvコマンドを使います。
仮想環境で使うPythonのバージョンを指定する際はuv venv --python 3.11といった感じでバージョン指定します。

適当なディレクトリに移動しuv venvコマンドを実行すると.venvディレクトリ配下に各種リソースを生成します。

Nushell
cd "<app-dir>"
uv venv --python 3.11

実行結果は以下の様になります。

Nushell
# .venv 配下に各種リソースが作成される
"<app-dir>"> uv venv --python 3.11
Using CPython 3.11.10
Creating virtual environment at: .venv
Activate with: overlay use .venv/Scripts/activate.nu

アクティベーション用のactivate.nuの実行を促されるので、overlayコマンドを使ってスクリプトを実行します。

他シェルと違いNushellではOverlaysという機能を介して仮想環境のアクティベーションを行います。

Nushell
# overlay use コマンドの引数に activate.nu を指定する
overlay use .venv/Scripts/activate.nu

結果は以下の様になり、他シェルの場合と同様の操作感となります。

Nushell
# アクティベーション前はシステムグローバルなPythonが使われる
"<app-dir>"> python -V
Python 3.12.7

# アクティベーション後は仮想環境のPythonが使われる
"<app-dir>"> overlay use .venv/Scripts/activate.nu

("env-name") "<app-dir>"> python -V
Python 3.11.10
("env-name") "<app-dir>"> which python
╭───┬─────────┬──────────────────────────────────────┬──────────╮
│ # │ command │                 path                 │   type   │
├───┼─────────┼──────────────────────────────────────┼──────────┤
│ 0 │ python  │ "<app-dir>"\.venv\Scripts\python.exe │ external │
╰───┴─────────┴──────────────────────────────────────┴──────────╯

仮想環境の利用を止める場合はdeactivateコマンドを実行します。

Nushell
# 仮想環境の利用を止める場合は deactivate を実行するだけでよい
deactivate

実行結果は以下。

Nushell
# deactivateコマンドで仮想環境の利用を停止
("env-name") "<app-dir>"> deactivate

# システムグローバルなPythonに戻る
"<app-dir>"> python -V
Python 3.12.7

ちなみにこのdeactivateコマンドはactivate.nuを実行した際に設定されたエイリアスで、実体となるコマンドはoverlay hideとなります。

activate.nu より引用
# deactivateエイリアスの実体はoverlay hideコマンド
export alias deactivate = overlay hide activate

このためdeactivateの代わりにoverlay hide activateを実行しても構いません。

その他コマンド

その他の処理についてはNushell固有のものが無いので割愛します。

補足 : NushellのOverlaysについて

前節で出てきた「Overlays」について軽く補足しておきます。

https://www.nushell.sh/book/overlays.html

これはNushell独自の機能で「カスタムコマンド」「エイリアス」「環境変数」の定義をレイヤー化するもので、用途としては正に今回の仮想環境といったものを作るために存在しています。

Nushellを起動した初期状態ではzeroと呼ばれる初期レイヤーが存在し、レイヤーの一覧はoverlay listコマンドで確認できます。

Nushell
# Nushell起動直後は zero レイヤーのみ存在
~> overlay list
╭───┬──────╮
│ 0 │ zero │
╰───┴──────╯

zeroとは別のレイヤーを作り利用するにはoverlay useコマンドを使います。
上記ドキュメントにある例を引用すると、環境変数の一式をspam.nuに保存し独自のレイヤーとして使うことができます。

Nushell
# 環境変数 FOO の定義を spam.nu に保存
'export-env { $env.FOO = "foo" }' | save spam.nu
# spam レイヤーを定義し切り替え
overlay use spam.nu

overlay useコマンドを実行した後はspamレイヤーが増え、このレイヤーの環境変数を参照できます。

Nushell
# overlay use コマンドを使うと新たにレイヤーが増える
~> ooverlay use spam.nu
~> overlay list
╭───┬──────╮
│ 0 │ zero │
│ 1 │ spam │
╰───┴──────╯

# 独自の環境変数を参照可能に
~> $env.FOO
foo

レイヤーを無くすにはoverlay hideコマンドを使います。
これで独自のspamレイヤーでの変更が無かったことになりzeroレイヤーに戻る形となります。

# overlay hide コマンドでレイヤーを削除
~> overlay hide spam

# zeroレイヤーに戻る
~> overlay list
╭───┬──────╮
│ 0 │ zero │
╰───┴──────╯

# spamレイヤーにあった環境変数は無かったことに
~> $env.FOO
Error: nu::shell::column_not_found

ここまでの説明を踏まえてvirtualenvやuvで使われているactivate.nuスクリプトをご覧いただくとより理解が深まると思います。

最後に

以上となります。

Pythonの開発環境周りは本当に多種多様なツールがあり情報を調べるのに苦労しました。
Nushell自体も破壊的変更がまだまだ多く将来的にガラッと状況が変わる可能性があります。

率直な気持ちとしては、安定した開発環境が必要な方にはまだNushellはお勧めできませんが、多少のトラブルは意に介さない、逆に燃えるといった方であれば楽しめると思います。
私はNushellに対する理解を深めたい思惑があったので調査を楽しめました。

本記事の内容が誰かの役に立てば幸いです。

脚注
  1. Nushellが破壊的変更をしすぎる ↩︎

Share this article

facebook logohatena logotwitter logo

© Classmethod, Inc. All rights reserved.